function pointCloudSegmentedCluster = cloudSegmentation(pointsFull, pointType)
    % pointsFull: Mx3 or  points
    params = struct();
    points = pointsFull;

    if isequal(pointType, 'hesai_p40p')
        % vertical_theta = [  15.00 11.00 8.00 5.00 3.00 2.00 1.67 1.33 ...
        %                 1.00 0.67 0.33 0.00 -0.33 -0.67 -1.00 -1.33 ...
        %                 -1.67 -2.00 -2.33 -2.67 -3.00 -3.33 -3.67 -4.00 ...
        %                 -4.33 -4.67 -5.00 -5.33 -5.67 -6.00 -7.00 -8.00 ...
        %                 -9.00 -10.00 -11.00 -12.00 -13.00 -14.00 -19.00 -25.00
        %                 ];

        vertical_theta = [7.14299997649533 ...
                        6.14199999369268 ...
                        5.13599998302528 ...
                        4.12799999379798 ...
                        3.11499999759304 ...
                        2.10199999817724 ...
                        1.76700000074352 ...
                        1.42100000085773 ...
                        1.08699999931673 ...
                        0.751999999400975 ...
                        0.406000000141502 ...
                        0.0709999999638067 ...
                        -0.268000000278996 ...
                        -0.606000000378927 ...
                        -0.945000000723587 ...
                        -1.28399999783447 ...
                        -1.62100000004531 ...
                        -1.95999999838307 ...
                        -2.29799999910524 ...
                        -2.63600000254155 ...
                        -2.97400000194410 ...
                        -3.31100000267718 ...
                        -3.64799999962323 ...
                        -3.98599999721783 ...
                        -4.31900000176996 ...
                        -4.66099999339903 ...
                        -4.99499999970970 ...
                        -5.32600000224023 ...
                        -5.66700000201380 ...
                        -5.99999999161288 ...
                        -7.00099998042811 ...
                        -7.99700000286255 ...
                        -8.98699999592648 ...
                        -9.97100001148963 ...
                        -10.9479999800399 ...
                        -11.9169999834595 ...
                        -12.8739999942060 ...
                        -13.8250000366970 ...
                        -14.7660000283462 ...
                        -15.6960000066476];

        vertical_theta = vertical_theta/180*pi;

        % set the params
        params.N_SCAN = 40;
        params.Horizon_SCAN = 1800;
        params.vertical_theta = vertical_theta;
        params.lidar_type = pointType;

        params.groundScanInd = 12;
        params.sensorMountAngle = 0;
        params.groundRemovalAngleT = 2;
        params.segmentTheta = 20/180.0*pi; % segmentTheta越小，簇越大，对深度的容忍越大；segmentTheta越大，簇越小，对深度变化的容忍度越小；
        params.feasibleSegmentValidPointNum = 30; % 30
        params.segmentValidPointNum = 5; % 5
        params.segmentValidLineNum = 3; % 3
        params.debugInfo = [18 7 14];
    elseif isequal(pointType, 'prescan_p40p')
        vertical_theta = [12.6749995304425 ...
                        12.0250000966667 ...
                        11.3749995623743 ...
                        10.7250002693310 ...
                        10.0750001292309 ...
                        9.42499975514755 ...
                        8.77500042464323 ...
                        8.12499945908174 ...
                        7.47499942750013 ...
                        6.82500032350010 ...
                        6.17500022246597 ...
                        5.52500003050543 ...
                        4.87500007595364 ...
                        4.22500001997206 ...
                        3.57499999086806 ...
                        2.92500015468267 ...
                        2.27499996486830 ...
                        1.62499999782561 ...
                        0.974999982567533 ...
                        0.325000020108150 ...
                        -0.324999994757377 ...
                        -0.975000007740665 ...
                        -1.62500002641223 ...
                        -2.27499999917517 ...
                        -2.92500009514571 ...
                        -3.57500001134124 ...
                        -4.22500004865302 ...
                        -4.87500014258578 ...
                        -5.52499996938786 ...
                        -6.17500032217496 ...
                        -6.82500036297083 ...
                        -7.47499942851741 ...
                        -8.12499963238950 ...
                        -8.77500046520763 ...
                        -9.42499966169597 ...
                        -10.0750001569357 ...
                        -10.7250001568748 ...
                        -11.3749995850157 ...
                        -12.0250000801206 ...
                        -12.6749994499319];

        vertical_theta = vertical_theta/180*pi;

        % set the params
        params.N_SCAN = 40;
        params.Horizon_SCAN = 1800;
        params.vertical_theta = vertical_theta;
        params.lidar_type = pointType;

        params.groundScanInd = 20;
        params.sensorMountAngle = 3;
        params.groundRemovalAngleT = 2;
        params.segmentTheta = 20/180.0*pi; % segmentTheta越小，簇越大，对深度的容忍越大；segmentTheta越大，簇越小，对深度变化的容忍度越小；
        params.feasibleSegmentValidPointNum = 30; % 30
        params.segmentValidPointNum = 5; % 5
        params.segmentValidLineNum = 3; % 3
        params.debugInfo = [18 7 14];
    end

    % you should convert the points from single to double, if you use the pcread, then the point type will be single
    [~, rangeMatFilled, ~, ~] = projectPointCloudMex(params, double(points));

    [labelMatFilled] = cloudSegmentationMex(params, double(rangeMatFilled), int8(zeros(size(rangeMatFilled))));

    labels = unique(labelMatFilled);
    cluster_num = length(labels);
    result = reshape(rangeMatFilled(:, :, 3:6), [], 4);
    pointCloudSegmentedCluster_num = 0;
    pointCloudSegmentedCluster = [];
    for i = 1 : cluster_num
        if labels(i) == 999999
            continue;
        end
        pointCloudSegmentedCluster_num = pointCloudSegmentedCluster_num + 1;
        label_index = find(labelMatFilled == labels(i));
        pointCloudSegmentedCluster{pointCloudSegmentedCluster_num} = result(label_index, :);
    end
end